import pytest
from errors import ParkingUnavailable
from fake_data import client_parkings as fake_data
from service import client_parkings as client_parkings_service


@pytest.fixture
def patched_data(monkeypatch):
    monkeypatch.setattr(
        client_parkings_service.data,
        "create_client_parking_json",
        fake_data.create_client_parking_json,
    )
    monkeypatch.setattr(
        client_parkings_service.data,
        "update_client_parking_json",
        fake_data.update_client_parking_json,
    )
    monkeypatch.setattr(
        client_parkings_service.data,
        "delete_client_parking",
        fake_data.delete_client_parking,
    )


def test_park_client(monkeypatch, patched_data):
    test_parking_id = 1
    test_client_id = 2

    def mock_is_parking_available(parking_id):
        # Убеждаемся, что функция проверки доступности вызвана с нужным parking_id.
        # Сама она у нас отдельно протестирована, так что достаточно проверить вызов.
        assert parking_id == test_parking_id
        return True

    def mock_decrease_places_count(parking_id):
        # Аналогичная проверка...
        assert parking_id == test_parking_id
        return None

    monkeypatch.setattr(
        client_parkings_service.parkings,
        "is_parking_available",
        mock_is_parking_available,
    )
    monkeypatch.setattr(
        client_parkings_service.parkings,
        "decrease_places_count",
        mock_decrease_places_count,
    )

    result = client_parkings_service.park_client(
        client_id=test_client_id, parking_id=test_parking_id
    )
    assert result["id"] == 300
    assert result["client_id"] == test_client_id
    assert result["parking_id"] == test_parking_id
    assert result["time_in"] is not None
    assert result["time_out"] is None


def test_park_client_unavailable(monkeypatch, patched_data):
    test_parking_id = 1

    def mock_is_parking_available(parking_id):
        # Убеждаемся, что функция проверки доступности вызвана с нужным parking_id.
        # Сама она у нас отдельно протестирована, так что достаточно проверить вызов.
        assert parking_id == test_parking_id
        return False

    monkeypatch.setattr(
        client_parkings_service.parkings,
        "is_parking_available",
        mock_is_parking_available,
    )

    with pytest.raises(ParkingUnavailable):
        client_parkings_service.park_client(client_id=1, parking_id=test_parking_id)


def test_end_parking(monkeypatch, patched_data):
    test_parking_id = 1
    test_client_id = 2
    client_parking = fake_data.get_client_parkings_list()[0]

    def mock_process_payment(client_id, parking_id, time_in, time_out):
        assert client_id == test_client_id
        assert parking_id == test_parking_id
        assert time_in == client_parking["time_in"]
        assert time_out is not None
        assert time_out > time_in

    def mock_increase_places_count(parking_id):
        assert parking_id == test_parking_id
        return None

    monkeypatch.setattr(
        client_parkings_service,
        "process_payment",
        mock_process_payment,
    )
    monkeypatch.setattr(
        client_parkings_service.parkings,
        "increase_places_count",
        mock_increase_places_count,
    )

    client_parkings_service.end_parking(
        client_id=test_client_id, parking_id=test_parking_id
    )
    assert len(fake_data.get_client_parkings_list()) == 0
